﻿using JGSY.SerialCommunication.UpperComputer.Core.EnumType;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace JGSY.SerialCommunication.UpperComputer.Core
{
    /// <summary>
    /// Modbus协议长度计算帮助类
    /// 支持各类Modbus协议的请求和响应长度计算
    /// </summary>
    public static class ModbusLengthCalculator
    {
        /// <summary>
        /// 将Modbus ASCII格式的字符串转换为十六进制字节数组
        /// 例如："010300000001840A" → [0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A]
        /// </summary>
        public static byte[] AsciiToHex(string asciiMessage)
        {
            // 移除起始符(:)和结束符(CRLF)
            if (asciiMessage.StartsWith(":"))
                asciiMessage = asciiMessage.Substring(1);

            if (asciiMessage.EndsWith("\r\n"))
                asciiMessage = asciiMessage.Substring(0, asciiMessage.Length - 2);

            // 检查长度是否为偶数（每个字节由两个ASCII字符表示）
            if (asciiMessage.Length % 2 != 0)
                throw new ArgumentException("ASCII消息长度必须为偶数");

            // 转换为字节数组
            byte[] result = new byte[asciiMessage.Length / 2];
            for (int i = 0; i < result.Length; i++)
            {
                string hexPair = asciiMessage.Substring(i * 2, 2);
                result[i] = Convert.ToByte(hexPair, 16);
            }

            return result;
        }
        /// <summary>
        /// 将字节数组转换为0x格式的十六进制字符串
        /// 例如：[1, 3, 0, 0, 1] → "0x01, 0x03, 0x00, 0x00, 0x01"
        /// </summary>
        public static string BytesToHexString(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return string.Empty;

            return string.Join(", ", bytes.Select(b => $"0x{b:X2}"));
        }
        /// <summary>
        /// 从Modbus ASCII格式的请求中提取PDU（协议数据单元）
        /// 例如：":010300000001840A" → [0x01, 0x03, 0x00, 0x00, 0x00, 0x01]
        /// </summary>
        public static byte[] ExtractPduFromAscii(string asciiFrame)
        {
            // 移除起始符(:)和结束符(CRLF)
            if (!asciiFrame.StartsWith(":") || !asciiFrame.EndsWith("\r\n"))
                throw new ArgumentException("无效的Modbus ASCII格式");

            string hexContent = asciiFrame.Substring(1, asciiFrame.Length - 3);

            // 验证长度（必须为偶数，因为每个字节由两个字符表示）
            if (hexContent.Length % 2 != 0)
                throw new ArgumentException("无效的十六进制字符串长度");

            // 提取PDU部分（去掉LRC校验的最后两个字符）
            string pduHex = hexContent.Substring(0, hexContent.Length - 2);

            // 转换为字节数组
            byte[] pdu = new byte[pduHex.Length / 2];
            for (int i = 0; i < pdu.Length; i++)
            {
                pdu[i] = Convert.ToByte(pduHex.Substring(i * 2, 2), 16);
            }

            // 验证LRC校验
            byte calculatedLrc = CalculateLrc(pdu);
            byte receivedLrc = Convert.ToByte(hexContent.Substring(hexContent.Length - 2, 2), 16);
            if (calculatedLrc != receivedLrc)
                throw new ArgumentException("LRC校验失败");

            return pdu;
        }

        /// <summary>
        /// 计算字节数组的LRC（纵向冗余校验）
        /// </summary>
        private static byte CalculateLrc(byte[] data)
        {
            int sum = 0;
            foreach (byte b in data)
            {
                sum += b;
            }

            return (byte)(-(sum & 0xFF));
        }
 



        /// <summary>
        /// 从Modbus ASCII格式的请求字节数组中提取PDU（协议数据单元）
        /// 例如：从 ":010300000001840A\r\n" 的字节数组提取为 [0x01, 0x03, 0x00, 0x00, 0x00, 0x01]
        /// </summary>
        public static byte[] ExtractPduFromAsciiBytes(byte[] request)
        {
            // 转换为字符串
            string asciiFrame = Encoding.ASCII.GetString(request);

            // 移除起始符(:)和结束符(CRLF)
            if (!asciiFrame.StartsWith(":") || !asciiFrame.EndsWith("\r\n"))
                throw new ArgumentException("无效的Modbus ASCII格式");

            string hexContent = asciiFrame.Substring(1, asciiFrame.Length - 3);

            // 验证长度（必须为偶数，因为每个字节由两个字符表示）
            if (hexContent.Length % 2 != 0)
                throw new ArgumentException("无效的十六进制字符串长度");

            // 提取PDU部分（去掉LRC校验的最后两个字符）
            string pduHex = hexContent.Substring(0, hexContent.Length - 2);

            // 转换为字节数组
            byte[] pdu = new byte[pduHex.Length / 2];
            for (int i = 0; i < pdu.Length; i++)
            {
                pdu[i] = Convert.ToByte(pduHex.Substring(i * 2, 2), 16);
            }

            // 验证LRC校验
            byte calculatedLrc = CalculateLrc(pdu);
            byte receivedLrc = Convert.ToByte(hexContent.Substring(hexContent.Length - 2, 2), 16);
            if (calculatedLrc != receivedLrc)
                throw new ArgumentException("LRC校验失败");

            return pdu;
        }

    



        #region 根据请求获取数据
        /// <summary>
        /// 从Modbus请求中提取数据内容
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <param name="request">请求字节数组</param>
        /// <returns>提取的数据内容</returns>
        public static ModbusRequestData ExtractDataFromRequest(ModbusProtocolType protocolType, byte[] request,bool IsIgnore=false)
        {
            if (request == null || request.Length < 2)
                throw new ArgumentException("请求数据无效");

            int functionCodeIndex = GetFunctionCodeIndex(protocolType);
            int unitIdIdex=6;
            //UDP忽略MABP
            if (IsIgnore) {
                unitIdIdex = 0;
                functionCodeIndex = functionCodeIndex - 6; 
            
            }
            int functionCode;
            int unitId;
            int startAddress;
            int dataCount;
            byte[] data;// 提取数据内容
            if (protocolType == ModbusProtocolType.Ascii)
            {
                //ParseAsciiFrame == ExtractPduFromAsciiBytes一样功能
                var bytes = ExtractPduFromAsciiBytes(request);
                functionCode = bytes[functionCodeIndex];
                unitId = bytes[0];
                startAddress = GetStartAddress(protocolType, functionCode, bytes, IsIgnore);
                dataCount = GetDataCountFromRequest(protocolType, functionCode, bytes, IsIgnore);
                data = ExtractDataBytes(protocolType, functionCode, bytes, IsIgnore);
            }
            else
            {
                functionCode = request[functionCodeIndex];
                unitId = protocolType == ModbusProtocolType.TcpIp || protocolType == ModbusProtocolType.UdpIp ? request[unitIdIdex] : request[0];
                startAddress = GetStartAddress(protocolType, functionCode, request, IsIgnore);
                dataCount = GetDataCountFromRequest(protocolType, functionCode, request, IsIgnore);
                data = ExtractDataBytes(protocolType, functionCode, request, IsIgnore);
            }
             
           

            return new ModbusRequestData
            {
                UnitId = unitId,
                FunctionCode = functionCode,
                StartAddress = startAddress,
                DataCount = dataCount,
                Data = data
            };
        }
        /// <summary>
        /// 获取起始地址下标8 、9
        /// </summary>
        /// <param name="protocolType">请求类型</param>
        /// <param name="functionCode">功能码</param>
        /// <param name="request">请求报文</param>
        /// <returns>返回起始地址</returns>
        private static int GetStartAddress(ModbusProtocolType protocolType, int functionCode, byte[] request,bool IsIgnore = false)
        {  
            int baseIndex = GetModbusBaseIndex(protocolType, IsIgnore);
            // 00 01 00 00 00 08 01 0F 00 [00 00] 06 01 36 
            return (request[baseIndex + 1] << 8) | request[baseIndex + 2];
        }
        /// <summary>
        /// 获取起始地址下标10 、11
        /// </summary>
        /// <param name="protocolType">请求类型</param>
        /// <param name="functionCode">功能码</param>
        /// <param name="request">请求报文</param>
        /// <returns>返回写入的数据数组【单个或多个】</returns>
        private static byte[] ExtractDataBytes(ModbusProtocolType protocolType, int functionCode, byte[] request, bool IsIgnore = false)
        {
            int baseIndex = (protocolType == ModbusProtocolType.TcpIp || protocolType == ModbusProtocolType.UdpIp) ? 7 : 1;
            if (IsIgnore) { baseIndex = baseIndex - 6; }
            //int baseIndex = GetModbusBaseIndex(protocolType, IsIgnore);
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                           // 这些功能码只包含地址和数量，没有数据字段
                    return Array.Empty<byte>();

                case 0x05: // 写单个线圈
                           // 提取值（两个字节，通常是0x0000或0xFF00）
                    return new byte[] { request[baseIndex + 3], request[baseIndex + 4] };

                case 0x06: // 写单个寄存器
                           // 提取寄存器值（两个字节）
                    return new byte[] { request[baseIndex + 3], request[baseIndex + 4] };
                case 0x0F: // 写多个线圈00 01 00 00 00 08 01 0F 00 00 00 06 [01] 36 
                    // 获取报文中的字节计数（存储线圈状态的字节数）
                    int byteCountCoil = request[baseIndex + 5];
                    
                    // 从请求中解析线圈数量
                    int coilCount = GetDataCountFromRequest(protocolType, functionCode, request);

                    // 验证报文总长度是否符合协议规范（固定部分 + 字节计数）
                    int expectedRequestLength = baseIndex + 5 + byteCountCoil; // 固定部分=7(MBAP)+1(功能码)+2(地址)+2(数量)+1(字节计数)=13
                    if (expectedRequestLength > request.Length)
                    {
                        throw new ArgumentException($"请求数据长度不足。预期至少{expectedRequestLength}字节，但实际只有{request.Length}字节。");
                    }

                    // 验证字节计数是否与线圈数量匹配（确保发送方正确计算了所需字节数）
                    int expectedByteCount = (coilCount + 7) / 8; // 向上取整
                    if (byteCountCoil != expectedByteCount)
                    {
                        throw new ArgumentException($"字节计数不匹配。线圈数量{coilCount}需要{expectedByteCount}字节，但报文中为{byteCountCoil}。");
                    }

                    // 创建结果数组，每个线圈对应一个字节(0xFF=ON, 0x00=OFF)
                    byte[] coilStatusBytes = new byte[coilCount];

                    // 线圈数据起始于baseIndex + 6（因为字节计数在baseIndex + 5位置）
                    // MBAP头(+ 单元标识符(1)=7)  + 功能码(1) + 地址(2) + 数量(2) + 字节计数(1) + 数据至少一个字节
                    int coilDataStartIndex = baseIndex + 6;

                    // 遍历每个字节
                    for (int i = 0; i < byteCountCoil; i++)
                    {
                        // 读取当前字节（修正索引计算）
                        byte currentByte = request[coilDataStartIndex + i];

                        // 处理当前字节中的每一位
                        for (int bitPos = 0; bitPos < 8; bitPos++)
                        {
                            // 计算当前线圈的索引（从0开始）
                            int currentCoilIndex = i * 8 + bitPos;
                            //0000 0000 0000 000
                            // 确保不处理超出请求数量的线圈
                            if (currentCoilIndex >= coilCount)
                                break;

                            // 检查位是否被设置(1表示ON，0表示OFF)
                            bool isCoilOn = (currentByte & (1 << bitPos)) != 0;

                            // 转换为Modbus标准字节值（0xFF=ON，0x00=OFF）
                            coilStatusBytes[currentCoilIndex] = isCoilOn ? (byte)0xFF : (byte)0x00;
                        }
                    }

                    return coilStatusBytes;
                //case 0x10: // 写多个寄存器00 01 00 00 00 08 01 0F 00 00 00 06 [01] 36 
                //    int byteCountReg = request[baseIndex + 5];
                //    // 验证字节计数是否合理（必须是偶数）
                //    if (byteCountReg % 2 != 0)
                //        throw new ArgumentException("寄存器数据字节数必须为偶数");
                //    // 修正：总长度 = MBAP(7) + 单元ID(1) + 功能码(1) + 地址(2) + 数量(2) + 字节计数(1) + 数据(n)
                //    if (baseIndex + 8 + byteCountReg > request.Length)
                //        throw new ArgumentException("请求数据长度不足");

                //    byte[] regData = new byte[byteCountReg];
                //    Array.Copy(request, baseIndex + 7, regData, 0, byteCountReg);
                //    return regData;
                case 0x10: // 写多个寄存器
                    int byteCountReg = request[baseIndex + 5];
                    // 验证字节计数是否合理（必须为偶数，因为每个寄存器占2字节）
                    if (byteCountReg % 2 != 0)
                        throw new ArgumentException("寄存器数据字节数必须为偶数");

                    // 计算预期的报文总长度
                    // 基础长度 = MBAP头(7) + 单元ID(1) + 功能码(1) + 起始地址(2) + 寄存器数量(2) + 字节计数(1) = baseIndex + 6
                    int expectedLength = baseIndex + 6 + byteCountReg;

                    //// 对于RTU/ASCII协议，还需要额外加上CRC(2字节)或LRC(2字节)
                    //if (protocolType == ModbusProtocolType.Rtu || protocolType == ModbusProtocolType.Ascii)
                    //    expectedLength += 2;

                    //// 对于RTU over TCP/UDP，需要加上CRC(2字节)
                    //if (protocolType == ModbusProtocolType.RtuOverTcpIp || protocolType == ModbusProtocolType.RtuOverUdpIp)
                    //    expectedLength += 2;

                    // 验证报文长度是否足够
                    if (request.Length < expectedLength)
                        throw new ArgumentException($"请求数据长度不足。预期至少{expectedLength}字节，但实际只有{request.Length}字节。");

                    // 提取寄存器数据（从字节计数后的位置开始）
                    byte[] regData = new byte[byteCountReg];
                    Array.Copy(request, baseIndex + 6, regData, 0, byteCountReg);
                    return regData;
                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }
        /// <summary>
        /// 将十进制整数数组转换为Modbus寄存器字节数据
        /// 例如：[4660] → [0x12, 0x34]（4660 = 0x1234）
        /// </summary>
        public static byte[] ConvertDecimalsToRegisters(int[] decimalValues)
        {
            if (decimalValues == null)
                throw new ArgumentNullException(nameof(decimalValues));

            byte[] result = new byte[decimalValues.Length * 2];

            for (int i = 0; i < decimalValues.Length; i++)
            {
                int value = decimalValues[i];

                // 确保数值在16位范围内
                if (value < 0 || value > 0xFFFF)
                    throw new ArgumentException($"数值 {value} 超出16位无符号整数范围（0-65535）");

                // 拆分为高字节和低字节
                result[i * 2] = (byte)((value >> 8) & 0xFF);     // 高字节
                result[i * 2 + 1] = (byte)(value & 0xFF);        // 低字节
            }

            return result;
        }
        /// <summary>
        /// 将Modbus寄存器字节数据转换为十进制整数数组
        /// 例如：[0x12, 0x34] → [4660]（0x1234 = 4660）
        /// </summary>
        public static int[] ConvertRegistersToDecimals(byte[] regData)
        {
            if (regData == null || regData.Length % 2 != 0)
                throw new ArgumentException("寄存器数据必须为偶数长度");

            int[] result = new int[regData.Length / 2];

            for (int i = 0; i < result.Length; i++)
            {
                // 高字节在前，低字节在后
                int highByte = regData[i * 2];
                int lowByte = regData[i * 2 + 1];

                // 组合为16位整数
                result[i] = (highByte << 8) | lowByte;
            }

            return result;
        }
        /// <summary>
        /// 辅助UDP忽略MABP时，解锁从站、功能码、数据、字节等的下表，以便提取内容数据
        /// UUIT和从站重复，是一样的 MABP-1
        /// </summary>
        /// <param name="protocolType"></param>
        /// <param name="IsIgnore"></param>
        /// <returns></returns>
        private static int GetModbusBaseIndex(ModbusProtocolType protocolType, bool IsIgnore)
        {
            int baseIndex = (protocolType == ModbusProtocolType.TcpIp || protocolType == ModbusProtocolType.UdpIp) ? 7 : 1;
            if (IsIgnore) { baseIndex = baseIndex - 6; }
            //UUID和从地址是一个7包含UUID
            return baseIndex;
        }

        #region 请求长度计算
        /// <summary>
        /// 计算Modbus请求的总长度
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <param name="functionCode">功能码</param>
        /// <param name="dataCount">数据数量（线圈/寄存器数量）</param>
        /// <returns>请求总长度（字节）</returns>
        public static int CalculateRequestLength(ModbusProtocolType protocolType, int functionCode, int dataCount)
        {
            switch (protocolType)
            {
                case ModbusProtocolType.UdpIp:
                    return CalculateUdpIpRequestLength(functionCode, dataCount);
                case ModbusProtocolType.RtuOverUdpIp:
                    return CalculateRtuOverUdpIpRequestLength(functionCode, dataCount);
                case ModbusProtocolType.TcpIp:
                    return CalculateTcpIpRequestLength(functionCode, dataCount);
                case ModbusProtocolType.RtuOverTcpIp:
                    return CalculateRtuOverTcpIpRequestLength(functionCode, dataCount);
                case ModbusProtocolType.Rtu:
                    return CalculateRtuRequestLength(functionCode, dataCount);
                case ModbusProtocolType.Ascii:
                    return CalculateAsciiRequestLength(functionCode, dataCount);
                default:
                    throw new ArgumentException($"不支持的协议类型: {protocolType}");
            }
        }
        /// <summary>
        /// 获取Udp请求总长度
        /// </summary>
        /// <param name="functionCode"></param>
        /// <param name="dataCount"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private static int CalculateUdpIpRequestLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                    return 8; // 单元标识符(1)+功能码(1)+地址(2)+数量(2)+CRC(2)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 8; // 单元标识符(1)+功能码(1)+地址(2)+值(2)+CRC(2)

                case 0x0F: // 写多个线圈
                    int coilBytes = (dataCount + 7) / 8;
                    return 11; // 单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(coilBytes)+CRC(2)

                case 0x10: // 写多个寄存器
                    return 15; // 单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(dataCount*2)+CRC(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuOverUdpIpRequestLength(int functionCode, int dataCount)
        {
            return CalculateUdpIpRequestLength(functionCode, dataCount);
        }
        /// <summary>
        /// 获取Tcp请求总长度
        /// </summary>
        /// <param name="functionCode"></param>
        /// <param name="dataCount"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private static int CalculateTcpIpRequestLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                    return 12; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 12; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+值(2)

                case 0x0F: // 写多个线圈
                    return 15; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(2)

                case 0x10: // 写多个寄存器
                    return 19; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(6)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuOverTcpIpRequestLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                    return 14; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)+CRC(2)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 14; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+值(2)+CRC(2)

                case 0x0F: // 写多个线圈
                    return 17; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(2)+CRC(2)

                case 0x10: // 写多个寄存器
                    return 21; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量(2)+字节计数(1)+数据(6)+CRC(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuRequestLength(int functionCode, int dataCount)
        {
            return CalculateUdpIpRequestLength(functionCode, dataCount);
        }
        /// <summary>
        /// 获取Ascii请求总长度
        /// </summary>
        /// <param name="functionCode"></param>
        /// <param name="dataCount"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private static int CalculateAsciiRequestLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                    return 17; // 起始符(1)+单元标识符(2)+功能码(2)+地址(4)+数量(4)+LRC(2)+结束符(2)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 17; // 起始符(1)+单元标识符(2)+功能码(2)+地址(4)+值(4)+LRC(2)+结束符(2)

                case 0x0F: // 写多个线圈
                    return 23; // 起始符(1)+单元标识符(2)+功能码(2)+地址(4)+数量(4)+字节计数(2)+数据(4)+LRC(2)+结束符(2)

                case 0x10: // 写多个寄存器
                    return 31; // 起始符(1)+单元标识符(2)+功能码(2)+地址(4)+数量(4)+字节计数(2)+数据(12)+LRC(2)+结束符(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }
        #endregion

        #region 响应长度计算
        /// <summary>
        /// 计算Modbus正常响应的总长度
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <param name="functionCode">功能码</param>
        /// <param name="dataCount">数据数量（线圈/寄存器数量）</param>
        /// <returns>响应总长度（字节）</returns>
        public static int CalculateNormalResponseLength(ModbusProtocolType protocolType, int functionCode, int dataCount)
        {
            switch (protocolType)
            {
                case ModbusProtocolType.UdpIp:
                    return CalculateUdpIpNormalResponseLength(functionCode, dataCount);
                case ModbusProtocolType.RtuOverUdpIp:
                    return CalculateRtuOverUdpIpNormalResponseLength(functionCode, dataCount);
                case ModbusProtocolType.TcpIp:
                    return CalculateTcpIpNormalResponseLength(functionCode, dataCount);
                case ModbusProtocolType.RtuOverTcpIp:
                    return CalculateRtuOverTcpIpNormalResponseLength(functionCode, dataCount);
                case ModbusProtocolType.Rtu:
                    return CalculateRtuNormalResponseLength(functionCode, dataCount);
                case ModbusProtocolType.Ascii:
                    return CalculateAsciiNormalResponseLength(functionCode, dataCount);
                default:
                    throw new ArgumentException($"不支持的协议类型: {protocolType}");
            }
        }
       /// <summary>
       /// 获取Udp响应的数据长度
       /// </summary>
       /// <param name="functionCode"></param>
       /// <param name="dataCount"></param>
       /// <returns></returns>
       /// <exception cref="ArgumentException"></exception>
        private static int CalculateUdpIpNormalResponseLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                    int coilBytes = (dataCount + 7) / 8;
                    return 5 + coilBytes; // 单元标识符(1)+功能码(1)+字节计数(1)+数据(coilBytes)+CRC(2)

                case 0x02: // 读离散输入
                    coilBytes = (dataCount + 7) / 8;
                    return 5 + coilBytes; // 单元标识符(1)+功能码(1)+字节计数(1)+数据(coilBytes)+CRC(2)

                case 0x03: // 读保持寄存器
                    return 11; // 单元标识符(1)+功能码(1)+字节计数(1)+数据(6)+CRC(2)

                case 0x04: // 读输入寄存器
                    return 13; // 单元标识符(1)+功能码(1)+字节计数(1)+数据(8)+CRC(2)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                case 0x0F: // 写多个线圈
                case 0x10: // 写多个寄存器
                    return 8; // 单元标识符(1)+功能码(1)+地址(2)+数量/值(2)+CRC(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuOverUdpIpNormalResponseLength(int functionCode, int dataCount)
        {
            return CalculateUdpIpNormalResponseLength(functionCode, dataCount);
        }
        /// <summary>
        /// 获取Tcp响应的数据长度
        /// </summary>
        /// <param name="functionCode"></param>
        /// <param name="dataCount"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private static int CalculateTcpIpNormalResponseLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                    int coilBytes = (dataCount + 7) / 8;
                    return 9 + coilBytes; // 修正：移除多余的+1，MBAP(7)+单元ID(1)+功能码(1)+字节计数(1)+数据(coilBytes)

                case 0x03: // 读保持寄存器
                    int regBytes = dataCount * 2; // 每个寄存器2字节
                    return 9 + regBytes; // 修正：动态计算数据长度

                case 0x04: // 读输入寄存器
                    regBytes = dataCount * 2;
                    return 9 + regBytes; // 修正：动态计算数据长度

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 12; // MBAP(7)+单元ID(1)+功能码(1)+地址(2)+值(2)

                case 0x0F: // 写多个线圈
                case 0x10: // 写多个寄存器
                    return 12; // MBAP(7)+单元ID(1)+功能码(1)+地址(2)+数量(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuOverTcpIpNormalResponseLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                    int coilBytes = (dataCount + 7) / 8;
                    return 11  + coilBytes; // MBAP头(7)+单元标识符(1)+功能码(1)+CRC(2)+字节计数(1)+数据(coilBytes)

                case 0x02: // 读离散输入
                    coilBytes = (dataCount + 7) / 8;
                    return 11  + coilBytes; // MBAP头(7)+单元标识符(1)+功能码(1)+CRC(2)+字节计数(1)+数据(coilBytes)

                case 0x03: // 读保持寄存器
                    return 17; // MBAP头(7)+单元标识符(1)+功能码(1)+CRC(2)+字节计数(1)+数据(6)

                case 0x04: // 读输入寄存器
                    return 19; // MBAP头(7)+单元标识符(1)+功能码(1)+CRC(2)+字节计数(1)+数据(8)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                case 0x0F: // 写多个线圈
                case 0x10: // 写多个寄存器
                    return 15; // MBAP头(7)+单元标识符(1)+功能码(1)+地址(2)+数量/值(2)+CRC(2)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }

        private static int CalculateRtuNormalResponseLength(int functionCode, int dataCount)
        {
            return CalculateUdpIpNormalResponseLength(functionCode, dataCount);
        }

        private static int CalculateAsciiNormalResponseLength(int functionCode, int dataCount)
        {
            switch (functionCode)
            {
                case 0x01: // 读线圈
                    int coilBytes = (dataCount + 7) / 8;
                    return 9 + 2 + (coilBytes * 2); // 起始符(1)+单元标识符(2)+功能码(2)+LRC(2)+结束符(2)+字节计数(2)+数据(coilBytes*2)

                case 0x02: // 读离散输入
                    coilBytes = (dataCount + 7) / 8;
                    return 9 + 2 + (coilBytes * 2); // 起始符(1)+单元标识符(2)+功能码(2)+LRC(2)+结束符(2)+字节计数(2)+数据(coilBytes*2)

                case 0x03: // 读保持寄存器
                    return 23; // 起始符(1)+单元标识符(2)+功能码(2)+LRC(2)+结束符(2)+字节计数(2)+数据(12)

                case 0x04: // 读输入寄存器
                    return 27; // 起始符(1)+单元标识符(2)+功能码(2)+LRC(2)+结束符(2)+字节计数(2)+数据(16)

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                case 0x0F: // 写多个线圈
                case 0x10: // 写多个寄存器
                    return 17; // 起始符(1)+单元标识符(2)+功能码(2)+LRC(2)+结束符(2)+地址(4)+数量/值(4)

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }
        #endregion

        #region 异常响应长度计算
        /// <summary>
        /// 计算Modbus异常响应的总长度
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <returns>异常响应总长度（字节）</returns>
        public static int CalculateExceptionResponseLength(ModbusProtocolType protocolType)
        {
            switch (protocolType)
            {
                case ModbusProtocolType.UdpIp:
                case ModbusProtocolType.RtuOverUdpIp:
                case ModbusProtocolType.Rtu:
                    return 5; // 单元标识符(1)+异常功能码(1)+异常码(1)+CRC(2)

                case ModbusProtocolType.TcpIp:
                    return 9; // MBAP头(7)+单元标识符(1)+异常功能码(1)+异常码(1)

                case ModbusProtocolType.RtuOverTcpIp:
                    return 11; // MBAP头(7)+单元标识符(1)+异常功能码(1)+异常码(1)+CRC(2)

                case ModbusProtocolType.Ascii:
                    return 11; // 起始符(1)+单元标识符(2)+异常功能码(2)+异常码(2)+LRC(2)+结束符(2)

                default:
                    throw new ArgumentException($"不支持的协议类型: {protocolType}");
            }
        }
        #endregion

        #region 根据请求获取响应长度
        /// <summary>
        /// 根据请求获取正常响应的总长度
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <param name="request">请求字节数组</param>
        /// <returns>正常响应总长度（字节）</returns>
        public static int GetNormalResponseLengthFromRequest(ModbusProtocolType protocolType, byte[] request)
        {
            if (request == null || request.Length < 2)
                throw new ArgumentException("请求数据无效");

            int functionCode = request[GetFunctionCodeIndex(protocolType)];
            int dataCount = GetDataCountFromRequest(protocolType, functionCode, request);

            return CalculateNormalResponseLength(protocolType, functionCode, dataCount);
        }

        /// <summary>
        /// 根据请求获取异常响应的总长度
        /// </summary>
        /// <param name="protocolType">协议类型</param>
        /// <returns>异常响应总长度（字节）</returns>
        public static int GetExceptionResponseLengthFromRequest(ModbusProtocolType protocolType)
        {
            return CalculateExceptionResponseLength(protocolType);
        }
        /// <summary>
        /// 获取请求报文功能码下标
        /// </summary>
        /// <param name="protocolType"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static int GetFunctionCodeIndex(ModbusProtocolType protocolType)
        {
            switch (protocolType)
            {
                case ModbusProtocolType.TcpIp:
                case ModbusProtocolType.UdpIp:
                    return 7; // MBAP头(7字节)后是功能码
                case ModbusProtocolType.Rtu:
                case ModbusProtocolType.Ascii:
                case ModbusProtocolType.RtuOverTcpIp:
                case ModbusProtocolType.RtuOverUdpIp:
                    return 1; // 直接从第0字节开始是功能码
                default:
                    throw new ArgumentException($"不支持的协议类型: {protocolType}");
            }
        }
        /// <summary>
        /// 返回字节数：占几个字节（数据数量或个数 ）
        /// </summary>
        /// <param name="protocolType"></param>
        /// <param name="functionCode"></param>
        /// <param name="request"></param>
        /// <param name="IsIgnore"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        private static int GetDataCountFromRequest(ModbusProtocolType protocolType, int functionCode, byte[] request,bool IsIgnore = false)
        { 
            int baseIndex = GetModbusBaseIndex(protocolType, IsIgnore);
            switch (functionCode)
            {
                case 0x01: // 读线圈
                case 0x02: // 读离散输入
                case 0x03: // 读保持寄存器
                case 0x04: // 读输入寄存器
                case 0x0F: // 写多个线圈
                case 0x10: // 写多个寄存器
                           // 修正：数据数量位于MBAP后的第3和第4字节（索引10-11）
                           // 00 01 00 00 00 08 01 0F 00 00 [00 06] 01 36
                    return (request[baseIndex + 3] << 8) | request[baseIndex + 4]; // 数量在第3、4字节

                case 0x05: // 写单个线圈
                case 0x06: // 写单个寄存器
                    return 1; // 固定为1个 

                default:
                    throw new ArgumentException($"不支持的功能码: {functionCode}");
            }
        }
        #endregion
    }

    /// <summary>
    /// 封装从Modbus请求中提取的数据
    /// </summary>
    public class ModbusRequestData
    {
        /// <summary>
        /// 单元标识符
        /// </summary>
        public int UnitId { get; set; }

        /// <summary>
        /// 功能码
        /// </summary>
        public int FunctionCode { get; set; }

        /// <summary>
        /// 起始地址
        /// </summary>
        public int StartAddress { get; set; }

        /// <summary>
        /// 数据数量（线圈/寄存器数量）
        /// </summary>
        public int DataCount { get; set; }

        /// <summary>
        /// 数据内容
        /// </summary>
        public byte[] Data { get; set; }
    }
    #endregion
}